package com.ruoyi.luban.service.impl;


import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import cn.binarywang.wx.miniapp.bean.WxMaUserInfo;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.common.utils.MD5Utils;
import com.google.gson.JsonSyntaxException;
import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.luban.domain.PUserAddress;
import com.ruoyi.luban.domain.PWxLoginUser;
import com.ruoyi.luban.domain.PWxUser;
import com.ruoyi.luban.domain.WXUserLoginInfo;
import com.ruoyi.luban.domain.dto.RegistAndBindUserDto;
import com.ruoyi.luban.domain.vo.LoginUserAndTokenVo;
import com.ruoyi.luban.domain.vo.WxLoginUserVo;
import com.ruoyi.luban.mapper.PUserAddressMapper;
import com.ruoyi.luban.mapper.PWxLoginUserMapper;
import com.ruoyi.luban.mapper.PWxUserMapper;
import com.ruoyi.luban.service.IPWxUserService;
import me.chanjar.weixin.common.error.WxErrorException;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 微信用户Service业务层处理
 * 
 * @author ruoyi
 * @date 2024-01-28
 */
@Service
public class PWxUserServiceImpl implements IPWxUserService
{
    protected final Logger logger = LoggerFactory.getLogger(this.getClass());
    @Autowired
    private PWxUserMapper pWxUserMapper;
    @Autowired
    private PWxLoginUserMapper pWxLoginUserMapper;
    @Autowired
    private PUserAddressMapper userAddressMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    WxMaService wxMaService;
    /**
     * 查询微信用户
     * 
     * @param id 微信用户主键
     * @return 微信用户
     */
    @Override
    public PWxUser selectPWxUserById(Long id)
    {
        return pWxUserMapper.selectPWxUserById(id);
    }

    /**
     * 查询微信用户列表
     * 
     * @param pWxUser 微信用户
     * @return 微信用户
     */
    @Override
    public List<PWxUser> selectPWxUserList(PWxUser pWxUser)
    {
        return pWxUserMapper.selectPWxUserList(pWxUser);
    }

    /**
     * 新增微信用户
     * 
     * @param pWxUser 微信用户
     * @return 结果
     */
    @Override
    public int insertPWxUser(PWxUser pWxUser)
    {
        pWxUser.setCreateTime(DateUtils.getNowDate());
        return pWxUserMapper.insertPWxUser(pWxUser);
    }

    /**
     * 修改微信用户
     * 
     * @param pWxUser 微信用户
     * @return 结果
     */
    @Override
    public int updatePWxUser(PWxUser pWxUser)
    {
        pWxUser.setUpdateTime(DateUtils.getNowDate());
        return pWxUserMapper.updatePWxUser(pWxUser);
    }

    /**
     * 批量删除微信用户
     * 
     * @param ids 需要删除的微信用户主键
     * @return 结果
     */
    @Override
    public int deletePWxUserByIds(Long[] ids)
    {
        return pWxUserMapper.deletePWxUserByIds(ids);
    }

    /**
     * 删除微信用户信息
     * 
     * @param id 微信用户主键
     * @return 结果
     */
    @Override
    public int deletePWxUserById(Long id)
    {
        return pWxUserMapper.deletePWxUserById(id);
    }

    @Override
    public String registerUserByWechat(WXUserLoginInfo wxUserLoginInfo) {
        PWxUser pWxUser = pWxUserMapper.selectPWxUserByOpenId(wxUserLoginInfo.getOpenId());
        if (pWxUser != null){
            pWxUser.setUpdateTime(new Date());
            pWxUserMapper.updatePWxUser(pWxUser);
        }else {
            //新增用户
            BeanUtils.copyProperties(wxUserLoginInfo,PWxUser.class);
            pWxUser.setDelFlag("0");
            pWxUser.setStatus("0");
            pWxUser.setUpdateTime(new Date());
            pWxUser.setCreateTime(new Date());
            pWxUserMapper.insertPWxUser(pWxUser);
        }

        String token = MD5Utils.encodeHexString(pWxUser.getOpenId().getBytes());
        //登录
        pWxUser = pWxUserMapper.selectPWxUserByOpenId(wxUserLoginInfo.getOpenId());
        wxUserLoginInfo.setUserId(pWxUser.getId());
        redisTemplate.opsForValue().set(token, JSON.toJSONString(wxUserLoginInfo), 5l,TimeUnit.MILLISECONDS);
        return token;
    }

    @Override
    public LoginUserAndTokenVo registWithWxFlow( LoginUserAndTokenVo info,RegistAndBindUserDto registAndBindParam) throws Exception {
        WxMaJscode2SessionResult sessionResult = null;
        if(info != null){
            sessionResult = new WxMaJscode2SessionResult();
            sessionResult.setOpenid(info.getMaOpenId());
            sessionResult.setSessionKey(info.getMaSessionKey());
            sessionResult.setUnionid("");
        }else {
            if (registAndBindParam.getMaOpenId() != null) {
                // 换回 wx code 对应的 open_id、union_id、session_key 信息
                sessionResult = new WxMaJscode2SessionResult();
                sessionResult.setOpenid(registAndBindParam.getMaOpenId());
                sessionResult.setSessionKey(registAndBindParam.getMaSessionKey());
                sessionResult.setUnionid(registAndBindParam.getUnionid());

            }
            else {
                sessionResult = wxMaService.getUserService().getSessionInfo(registAndBindParam.getCode());
            }
        }
        logger.info("registWithWxFlow:获取用户信息:{}",JSON.toJSONString(sessionResult));
        //插入微信用户
        PWxUser pWxUser = pWxUserMapper.selectPWxUserByOpenId(sessionResult.getOpenid());
        PWxLoginUser pWxLoginUser = null;
        if (pWxUser != null){
            pWxUser.setUpdateTime(new Date());
            pWxUserMapper.updatePWxUser(pWxUser);
            pWxLoginUser = pWxLoginUserMapper.selectPWxLoginUserByOpenId(sessionResult.getOpenid());
            if(pWxLoginUser != null) {
                pWxLoginUser.setUpdateTime(new Date());
                pWxLoginUserMapper.updatePWxLoginUser(pWxLoginUser);
            }else{
                pWxLoginUser = new PWxLoginUser();
                pWxLoginUser.setOpenId(pWxUser.getOpenId());
                pWxLoginUser.setLoginName(pWxUser.getPhone());//默认手机号
                pWxLoginUser.setLoginType(registAndBindParam.getLoginType());
                pWxLoginUser.setLoginUrl(pWxUser.getAvatarUrl());
                pWxLoginUser.setNickName(pWxUser.getNickName());
                pWxLoginUser.setUpdateTime(new Date());
                pWxLoginUser.setCreateTime(new Date());
                pWxLoginUserMapper.insertPWxLoginUser(pWxLoginUser);
            }
        }else {
            //传递微信用户数据是否为空
            if(StringUtils.isBlank(registAndBindParam.getEncryptedData()) && StringUtils.isBlank(registAndBindParam.getUserInfo()+"")){
                logger.error("registWithWxFlow,注册失败,传递参数" + JSON.toJSONString(registAndBindParam));
                throw new Exception("注册失败,传递参数");
            }
            // 解密微信用户的数据
            WxMaUserInfo wxMaUserInfo = null;
            WxMaPhoneNumberInfo wxMaPhoneNumberInfo = null;
            try {
                logger.info("sessionKey:{}",sessionResult.getSessionKey());
                logger.info("encryptedData:{}",registAndBindParam.getEncryptedData());
                if(registAndBindParam.getUserInfo() != null && !"微信用户".equals(registAndBindParam.getUserInfo().getNickName())){
                    //如果前端传递，直接由前端获取
                    wxMaUserInfo =  (WxMaUserInfo) JSON.parseObject(JSON.toJSONString(registAndBindParam.getUserInfo()), WxMaUserInfo.class);
                    wxMaUserInfo.setUnionId(sessionResult.getUnionid());

                }else{
                    wxMaUserInfo = wxMaService.getUserService().getUserInfo(sessionResult.getSessionKey(), registAndBindParam.getEncryptedData(), registAndBindParam.getIv());
                    if("微信用户".equals(wxMaUserInfo.getNickName()) && registAndBindParam.getUserInfo() != null){
                        wxMaUserInfo.setNickName(registAndBindParam.getUserInfo().getNickName());
                    }
                    wxMaUserInfo.setUnionId(sessionResult.getUnionid());
                    logger.info("微信获取解密用户数据：wxMaUserInfo:{}" ,JSON.toJSONString(wxMaUserInfo));

                }
            } catch (Exception e) {
                e.printStackTrace();
                logger.error("registWithWxFlow,解密失败:" + registAndBindParam.toString());
                throw new Exception("registWithWxFlow,解密失败:" + registAndBindParam.toString());
            }
            if(registAndBindParam.getPhoneEncryptedData() != null) {
                try {
                    wxMaPhoneNumberInfo = wxMaService.getUserService().getPhoneNoInfo(sessionResult.getSessionKey(), registAndBindParam.getPhoneEncryptedData(), registAndBindParam.getPhoneIv());
                }catch (Exception e){
                    e.printStackTrace();
                    logger.error("微信电话数据解码失败");
                }
            }
            logger.info("pure wx userInfo: " + JSON.toJSONString(wxMaUserInfo));
            pWxUser = new PWxUser();
            //新增用户
            BeanUtils.copyProperties(wxMaUserInfo, pWxUser);
            Integer gender = Integer.parseInt(wxMaUserInfo.getGender());
            pWxUser.setGender(gender);
            pWxUser.setUpdateTime(new Date());
            pWxUser.setCreateTime(new Date());
            pWxUser.setOpenId(sessionResult.getOpenid());
            pWxUser.setIsSubscribe(1);
            if (wxMaPhoneNumberInfo != null) {
                pWxUser.setPhone(wxMaPhoneNumberInfo.getPhoneNumber());
            }
            pWxUserMapper.insertPWxUser(pWxUser);
            pWxLoginUser = new PWxLoginUser();
            //插入登录用户
            pWxLoginUser.setOpenId(pWxUser.getOpenId());
//            pWxLoginUser.setContactId(pWxUser.getId());
            pWxLoginUser.setPhone(pWxUser.getPhone());//默认手机号
            pWxLoginUser.setLoginType(registAndBindParam.getLoginType());
            pWxLoginUser.setLoginUrl(pWxUser.getAvatarUrl());
            pWxLoginUser.setNickName(pWxUser.getNickName());
//            pWxLoginUser.setStatus("0");
            pWxLoginUser.setUpdateTime(new Date());
            pWxLoginUser.setCreateTime(new Date());
            pWxLoginUserMapper.insertPWxLoginUser(pWxLoginUser);
        }
        //学校登录不需要插入登录账号，需要指定登录
        WxLoginUserVo userVo = new WxLoginUserVo();
        LoginUserAndTokenVo loginUserAndTokenVo = new LoginUserAndTokenVo();
        loginUserAndTokenVo.setMaOpenId(sessionResult.getOpenid());
        loginUserAndTokenVo.setMaUnionId(sessionResult.getUnionid());
        loginUserAndTokenVo.setMaSessionKey(sessionResult.getSessionKey());
        loginUserAndTokenVo.setLoginUser(userVo);
        loginUserAndTokenVo.setLoginType(pWxLoginUser.getLoginType());
        loginUserAndTokenVo.setToBind("1");
//        loginUserAndTokenVo.setLoginType(registAndBindParam.getLoginType());
        userVo.setLoginName(pWxLoginUser.getLoginName());
        userVo.setNickName(pWxLoginUser.getNickName());
        userVo.setLoginUrl(pWxLoginUser.getLoginUrl());
        userVo.setPhone(pWxLoginUser.getPhone());
        userVo.setLoginUserId(pWxLoginUser.getId());
        if("1".equals(pWxLoginUser.getLoginType())){
            userVo.setPhone(pWxLoginUser.getLoginName());
        }
        String token = MD5Utils.encodeHexString(pWxUser.getOpenId().getBytes());
//        redisTemplate.opsForValue().set(token, JSON.toJSONString(loginUserAndTokenVo), 1,TimeUnit.DAYS);
        loginUserAndTokenVo.setAuthToken(token);
        return loginUserAndTokenVo;
    }

    @Override
    public LoginUserAndTokenVo loginWithWxFlow(String code, String openId) throws WxErrorException {
        PWxLoginUser pWxLoginUser = new PWxLoginUser();
        String openid = null;
        String session_key = "";
        String unionid = "";
        if(StringUtils.isNotBlank(openId)){
            openid = openId;
        }else{
            // 换回 wx code 对应的 open_id、union_id、session_key 信息
            WxMaJscode2SessionResult sessionResult = wxMaService.getUserService().getSessionInfo(code);
            openid = sessionResult.getOpenid();
            session_key = sessionResult.getSessionKey();
            unionid = sessionResult.getUnionid();
        }
        LoginUserAndTokenVo loginUserAndTokenVo = new LoginUserAndTokenVo();
        WxLoginUserVo userVo = new WxLoginUserVo();
        String token = MD5Utils.encodeHexString(openid.getBytes());
        loginUserAndTokenVo.setAuthToken(token);
        loginUserAndTokenVo.setMaOpenId(openid);
        loginUserAndTokenVo.setMaUnionId(unionid);
        loginUserAndTokenVo.setToBind("-1");//默认要去绑定账号数据
        loginUserAndTokenVo.setMaSessionKey(session_key);
        //获取用户微信登录绑定账号信息

        pWxLoginUser.setOpenId(openid);

        List<PWxLoginUser> pWxLoginUsers = pWxLoginUserMapper.selectPWxLoginUserList(pWxLoginUser);
        if(pWxLoginUsers.isEmpty()){
            return loginUserAndTokenVo;
        }
        logger.info("获取数据登录用户数据:"+ JSONObject.toJSONString(pWxLoginUsers));
        loginUserAndTokenVo.setToBind("1");
        pWxLoginUser = pWxLoginUsers.get(0);

        userVo.setLoginName(pWxLoginUser.getLoginName());
        userVo.setNickName(pWxLoginUser.getNickName());
        userVo.setLoginUrl(pWxLoginUser.getLoginUrl());
        userVo.setLoginUserId(pWxLoginUser.getId());
        userVo.setPhone(pWxLoginUser.getPhone());
        userVo.setLoginUserId(pWxLoginUser.getId());
        String loginType= pWxLoginUser.getLoginType();
        if("1".equals(loginType)){
            userVo.setPhone(pWxLoginUser.getLoginName());
        }
        loginUserAndTokenVo.setLoginType(loginType);
        loginUserAndTokenVo.setLoginUser(userVo);
        loginUserAndTokenVo.setSubscribeStatus(pWxLoginUser.getSubscribeStatus());
//        loginUserAndTokenVo.setToBind("0");//1 要去绑定，0不用绑定
        //判断是否绑定账号，或者学校
        if("2".equals(pWxLoginUser.getStatus())){//需要
            loginUserAndTokenVo.setToBind("0");
            if(loginType.equals("2")){//学校
                PUserAddress pUserAddress = new PUserAddress();
                pUserAddress.setOpenId(openid);
                List<PUserAddress> pUserAddresses = userAddressMapper.selectPUserAddressList(pUserAddress);
                if(!pUserAddresses.isEmpty()){
                    loginUserAndTokenVo.setSchoolId(pUserAddresses.get(0).getSchoolId());
                    loginUserAndTokenVo.setSchoolName(pUserAddresses.get(0).getSchoolName());
                }
            }
        }
//        redisTemplate.opsForValue().set(token, JSON.toJSONString(loginUserAndTokenVo), 1,TimeUnit.DAYS);
        return loginUserAndTokenVo;
    }

    @Override
    public LoginUserAndTokenVo saveSubscribeStatus(LoginUserAndTokenVo info, String subscribeStatus) {
        //获取登录用户
        PWxLoginUser pWxLoginUser = pWxLoginUserMapper.selectPWxLoginUserById(info.getLoginUser().getLoginUserId());
        pWxLoginUser.setSubscribeStatus(subscribeStatus);
        pWxLoginUserMapper.updatePWxLoginUser(pWxLoginUser);
        info.setSubscribeStatus(subscribeStatus);
        return info;
    }

}
